package com.uaf.vxalipaybill.provider.shardingjdbc;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.SortedMap;

import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.RangeShardingValue;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.uaf.log.MySlf4j;
import com.uaf.vxalipaybill.provider.bean.VxAlipayBillAnalysisReqBean;
import com.uaf.vxalipaybill.provider.dao.VxAlipayBillAnalysisReqBeanDao;

/**
 * @filename ConsistentShardingAlgorithm.java
 * @description  精确分片确定数据在哪个具体的表
 * @author 马庆智
 * @date 2022/3/31 16:34
 */
@Component
public class ConsistentShardingAlgorithm implements PreciseShardingAlgorithm<String>, RangeShardingAlgorithm<String> {

	/**
	 * 精确分片
	 * 一致性hash算法
	 */
	@Override
	public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {

		//获取已经初始化的分表节点
		InitTableNodesToHashLoop initTableNodesToHashLoop = (InitTableNodesToHashLoop) SpringContextUtils
				.getBean(InitTableNodesToHashLoop.class);

		if (CollectionUtils.isEmpty(availableTargetNames)) {
			return shardingValue.getLogicTableName();
		}
		//这里主要为了兼容当联表查询时，如果两个表非关联表则
		//当对副表分表时shardingValue这里传递进来的依然是主表的名称，
		//但availableTargetNames中确是副表名称，所有这里要从availableTargetNames中匹配真实表
		ArrayList<String> availableTargetNameList = new ArrayList<>(availableTargetNames);
		String logicTableName = availableTargetNameList.get(0).replaceAll("[^(a-zA-Z_)]", "");
		/**虚拟*/
		if (!StringUtils.isEmpty(initTableNodesToHashLoop)) {
			HashMap<String, SortedMap<Long, String>> tableVirtualNodes = initTableNodesToHashLoop
					.getTableVirtualNodes();
			SortedMap<Long, String> tableHashNode = tableVirtualNodes.get(logicTableName);

			ConsistentHashAlgorithm consistentHashAlgorithm = new ConsistentHashAlgorithm(tableHashNode,
					availableTargetNames);

			MySlf4j.textDebug("reqId的值为{0},对应sql查询的表为:{1},", String.valueOf(shardingValue.getValue()),
					consistentHashAlgorithm.getTableNode(String.valueOf(shardingValue.getValue())));

			/**根据保存请求id对应的表*/
			VxAlipayBillAnalysisReqBean vxAlipayBillAnalysisReqBean = new VxAlipayBillAnalysisReqBean();
			vxAlipayBillAnalysisReqBean.setBillAnalysisReqId(Integer.parseInt(shardingValue.getValue()));
			vxAlipayBillAnalysisReqBean
					.setRemark(consistentHashAlgorithm.getTableNode(String.valueOf(shardingValue.getValue())));
			VxAlipayBillAnalysisReqBeanDao vxAlipayBillAnalysisReqBeanDao = SpringContextUtils
					.getBean(VxAlipayBillAnalysisReqBeanDao.class);
			vxAlipayBillAnalysisReqBeanDao.updateVxAlipayBillAnalysisReqBean(vxAlipayBillAnalysisReqBean);

			return consistentHashAlgorithm.getTableNode(String.valueOf(shardingValue.getValue()));

		} else {

			ConsistentHashAlgorithm consistentHashAlgorithm = new ConsistentHashAlgorithm(null, availableTargetNames);

			MySlf4j.textDebug("reqId的值为{0},对应sql查询的表为:{1},", String.valueOf(shardingValue.getValue()),
					consistentHashAlgorithm.getTableNode(String.valueOf(shardingValue.getValue())));

			/**根据保存请求id对应的表*/
			VxAlipayBillAnalysisReqBean vxAlipayBillAnalysisReqBean = new VxAlipayBillAnalysisReqBean();
			vxAlipayBillAnalysisReqBean.setBillAnalysisReqId(Integer.parseInt(shardingValue.getValue()));
			vxAlipayBillAnalysisReqBean
					.setRemark(consistentHashAlgorithm.getTableNode(String.valueOf(shardingValue.getValue())));
			VxAlipayBillAnalysisReqBeanDao vxAlipayBillAnalysisReqBeanDao = SpringContextUtils
					.getBean(VxAlipayBillAnalysisReqBeanDao.class);
			vxAlipayBillAnalysisReqBeanDao.updateVxAlipayBillAnalysisReqBean(vxAlipayBillAnalysisReqBean);

			return consistentHashAlgorithm.getTableNode(String.valueOf(shardingValue.getValue()));
		}

	}


	/**
	 * 功能描述 范围查询规则
	 * @param availableTargetNames
	 * @param rangeShardingValue
	 * @return java.util.Collection<java.lang.String>
	 * @author 马庆智
	 * @date 2022/2/21 17:27
	 */
	@Override
	public Collection<String> doSharding(Collection<String> availableTargetNames,
			RangeShardingValue<String> rangeShardingValue) {
		return availableTargetNames;
	}
}